/*
 * Copyright (C) 2016 Lokiy(liulongke@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  　　　　http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

@file:Suppress("DEPRECATION", "unused")

package com.lokiy.kit.utils

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.os.Build
import android.view.ViewGroup
import androidx.drawerlayout.widget.DrawerLayout
import android.widget.LinearLayout
import android.view.WindowManager
import kotlin.jvm.JvmOverloads
import android.util.TypedValue
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.lokiy.kit.ktx.getOrNull

/**
 * Created by Lokiy on 2017/8/17.
 *
 */
class StatusBarUtils private constructor(private val mActivity: Activity, config: StatusBarConfig? = null) {
    private var statusBarConfig: StatusBarConfig

    class StatusBarConfig {
        //状态栏颜色
        var mColor = -1

        //状态栏drawable
        var mDrawable: Drawable? = null

        //是否是最外层布局是 DrawerLayout 的侧滑菜单
        var isDrawerLayout = false

        //是否包含 ActionBar
        var isActionBar = false

        //侧滑菜单页面的内容视图
        var mContentResourceIdInDrawer = 0
        var isDark = false
        var immersive = false
    }

    /**
     * 设置是否是沉浸式 默认true
     *
     * @param immersive 沉浸式
     */
    fun immersive(immersive: Boolean): StatusBarUtils {
        statusBarConfig.immersive = immersive
        return this
    }

    /**
     * 设置虚拟状态栏背景颜色
     *
     * @param color color
     */
    fun color(color: Int): StatusBarUtils {
        statusBarConfig.mColor = color
        return this
    }

    /**
     * 设置虚拟状态栏背景drawable
     *
     * @param drawable drawable
     */
    fun drawable(drawable: Drawable?): StatusBarUtils {
        statusBarConfig.mDrawable = drawable
        return this
    }

    /**
     * 设置statusBar文字颜色是否是黑色 默认是白色
     *
     * @param isDark isDark
     */
    fun dark(isDark: Boolean): StatusBarUtils {
        statusBarConfig.isDark = isDark
        return this
    }

    fun isActionBar(actionBar: Boolean): StatusBarUtils {
        statusBarConfig.isActionBar = actionBar
        return this
    }

    /**
     * 是否是最外层布局为 DrawerLayout 的侧滑菜单
     *
     * @param drawerLayout 是否最外层布局为 DrawerLayout
     * @param contentId    内容视图的 id
     */
    fun setDrawerLayoutContentId(drawerLayout: Boolean, contentId: Int): StatusBarUtils {
        statusBarConfig.isDrawerLayout = drawerLayout
        statusBarConfig.mContentResourceIdInDrawer = contentId
        return this
    }

    /**
     * 去除 ActionBar 阴影
     */
    fun clearActionBarShadow(): StatusBarUtils {
        if (Build.VERSION.SDK_INT >= 21) {
            val supportActionBar = (mActivity as AppCompatActivity).supportActionBar
            if (supportActionBar != null) {
                supportActionBar.elevation = 0f
            }
        }
        return this
    }

    fun apply() {
        if (statusBarConfig.immersive) {
            fullScreen(mActivity)
        }
        if (statusBarConfig.isDark) {
            val window = mActivity.window
            val decorView = window.decorView
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                decorView.systemUiVisibility = decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
            }
        } else {
            val window = mActivity.window
            val decorView = window.decorView
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                decorView.systemUiVisibility = decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            }
        }
        if (statusBarConfig.mColor != -1) {
            //设置了状态栏颜色
            addStatusViewWithColor(mActivity, statusBarConfig.mColor)
        }
        if (statusBarConfig.mDrawable != null) {
            //设置了状态栏 drawable，例如渐变色
            addStatusViewWithDrawable(mActivity, statusBarConfig.mDrawable)
        }
        if (statusBarConfig.isDrawerLayout) {
            //未设置 fitsSystemWindows 且是侧滑菜单，需要设置 fitsSystemWindows 以解决 4.4 上侧滑菜单上方白条问题
            fitsSystemWindows(mActivity)
        }
        if (statusBarConfig.isActionBar) {
            //要增加内容视图的 paddingTop,否则内容被 ActionBar 遮盖
            val window = mActivity.window
            val rootView = window.decorView.findViewById<ViewGroup>(android.R.id.content)
            rootView.setPadding(0, getStatusBarHeight(mActivity) + getActionBarHeight(mActivity), 0, 0)
        }
    }

    /**
     * 设置页面最外层布局 FitsSystemWindows 属性
     *
     * @param activity activity
     */
    private fun fitsSystemWindows(activity: Activity) {
        val contentFrameLayout = activity.findViewById<ViewGroup>(android.R.id.content)
        val parentView = contentFrameLayout.getChildAt(0)
        if (parentView != null) {
            parentView.fitsSystemWindows = true
            //布局预留状态栏高度的 padding
            if (parentView is DrawerLayout) {
                //将主页面顶部延伸至status bar;虽默认为false,但经测试,DrawerLayout需显示设置
                parentView.clipToPadding = false
            }
        }
    }

    /**
     * 添加状态栏占位视图
     *
     * @param activity activity
     */
    private fun addStatusViewWithColor(activity: Activity, color: Int) {
        if (statusBarConfig.isDrawerLayout) {
            //要在内容布局增加状态栏，否则会盖在侧滑菜单上
            val rootView = activity.findViewById<ViewGroup>(android.R.id.content)
            //DrawerLayout 则需要在第一个子视图即内容试图中添加padding
            val parentView = rootView.getChildAt(0)
            if (parentView is DrawerLayout) {
                if (parentView.childCount > 0 && "addStatusViewWithColor-LinearLayout" == parentView.getOrNull(0)?.tag.toString()) {
                    return
                }
                val linearLayout = LinearLayout(activity)
                linearLayout.tag = "addStatusViewWithColor-LinearLayout"
                linearLayout.orientation = LinearLayout.VERTICAL
                val statusBarView = View(activity)
                val lp = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity))
                statusBarView.setBackgroundColor(color)
                //添加占位状态栏到线性布局中
                linearLayout.addView(statusBarView, lp)
                //侧滑菜单
                //内容视图
                val content = activity.findViewById<View>(statusBarConfig.mContentResourceIdInDrawer)
                //将内容视图从 DrawerLayout 中移除
                parentView.removeView(content)
                //添加内容视图
                linearLayout.addView(content, content.layoutParams)
                //将带有占位状态栏的新的内容视图设置给 DrawerLayout
                parentView.addView(linearLayout, 0)
            }
        } else {
            //设置 paddingTop
            val rootView = mActivity.window.decorView.findViewById<ViewGroup>(android.R.id.content)
            rootView.setPadding(0, getStatusBarHeight(mActivity), 0, 0)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                //直接设置状态栏颜色
                activity.window.statusBarColor = color
            } else {
                //增加占位状态栏
                val decorView = mActivity.window.decorView as ViewGroup
                if (decorView.findViewWithTag<View?>("addStatusViewWithColor-View") != null) {
                    return
                }
                val statusBarView = View(activity)
                statusBarView.tag = "addStatusViewWithColor-View"
                val lp = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity))
                statusBarView.setBackgroundColor(color)
                decorView.addView(statusBarView, lp)
            }
        }
    }

    /**
     * 添加状态栏占位视图
     *
     * @param activity activity
     */
    private fun addStatusViewWithDrawable(activity: Activity, drawable: Drawable?) {
        //占位状态栏
        val statusBarView = View(activity)
        val lp = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity))
        statusBarView.background = drawable
        if (statusBarConfig.isDrawerLayout) {
            //要在内容布局增加状态栏，否则会盖在侧滑菜单上
            val rootView = activity.findViewById<ViewGroup>(android.R.id.content)
            //DrawerLayout 则需要在第一个子视图即内容试图中添加padding
            val parentView = rootView.getChildAt(0)
            val linearLayout = LinearLayout(activity)
            linearLayout.orientation = LinearLayout.VERTICAL
            //添加占位状态栏到线性布局中
            linearLayout.addView(statusBarView, lp)
            //侧滑菜单
            val drawer = parentView as DrawerLayout
            //内容视图
            val content = activity.findViewById<View>(statusBarConfig.mContentResourceIdInDrawer)
            //将内容视图从 DrawerLayout 中移除
            drawer.removeView(content)
            //添加内容视图
            linearLayout.addView(content, content.layoutParams)
            //将带有占位状态栏的新的内容视图设置给 DrawerLayout
            drawer.addView(linearLayout, 0)
        } else {
            //增加占位状态栏，并增加状态栏高度的 paddingTop
            val decorView = mActivity.window.decorView as ViewGroup
            decorView.addView(statusBarView, lp)
            //设置 paddingTop
            val rootView = mActivity.window.decorView.findViewById<ViewGroup>(android.R.id.content)
            rootView.setPadding(0, getStatusBarHeight(mActivity), 0, 0)
        }
    }

    /**
     * 通过设置全屏，设置状态栏透明
     *
     * @param activity activity
     */
    private fun fullScreen(activity: Activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            //5.x开始需要把颜色设置透明，否则导航栏会呈现系统默认的浅灰色
            val window = activity.window
            val decorView = window.decorView
            //两个 flag 要结合使用，表示让应用的主体内容占用系统状态栏的空间
            val option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            decorView.systemUiVisibility = option
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
            window.statusBarColor = Color.TRANSPARENT
            //导航栏颜色也可以正常设置
//                window.setNavigationBarColor(Color.TRANSPARENT);
        } else {
            val window = activity.window
            val attributes = window.attributes
            val flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
//            val flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
            attributes.flags = attributes.flags or flagTranslucentStatus
            //                attributes.flags |= flagTranslucentNavigation;
            window.attributes = attributes
        }
    }

    companion object {
        @JvmOverloads
        @JvmStatic
        fun with(activity: Activity, config: StatusBarConfig? = null): StatusBarUtils {
            return StatusBarUtils(activity, config)
        }

        /**
         * 利用反射获取状态栏高度
         *
         * @return height
         */
        @SuppressLint("InternalInsetResource")
        fun getStatusBarHeight(activity: Activity): Int {
            var result = 0
            //获取状态栏高度的资源id
            val resourceId = activity.resources.getIdentifier("status_bar_height", "dimen", "android")
            if (resourceId > 0) {
                result = activity.resources.getDimensionPixelSize(resourceId)
            }
            //        loge("getStatusBarHeight" + result + "");
            return result
        }

        /**
         * 获得 ActionBar 的高度
         *
         * @param context context
         * @return height
         */
        fun getActionBarHeight(context: Context): Int {
            val tv = TypedValue()
            context.theme.resolveAttribute(android.R.attr.actionBarSize, tv, true)
            return TypedValue.complexToDimensionPixelSize(tv.data, context.resources.displayMetrics)
        }

        /**
         * 通过设置全屏，设置状态栏透明 导航栏黑色
         *
         * @param activity activity
         */
        fun setStatusTransparent(activity: Activity) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                val window = activity.window
                val attributes = window.attributes
//                val flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                val flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
                //                attributes.flags |= flagTranslucentStatus;
                attributes.flags = attributes.flags or flagTranslucentNavigation
                window.attributes = attributes
                window.decorView.systemUiVisibility =
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
                window.statusBarColor = Color.TRANSPARENT
                window.navigationBarColor = Color.TRANSPARENT
            } else {
                val window = activity.window
                val attributes = window.attributes
                val flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                val flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
                attributes.flags = attributes.flags or flagTranslucentStatus
                attributes.flags = attributes.flags or flagTranslucentNavigation
                window.attributes = attributes
            }
        }
    }

    init {
        statusBarConfig = config ?: StatusBarConfig()
    }
}